package com.common.util;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.*;

/**
 * @describe 压缩多个文件
 * @author liuchao
 * @date 2018年1月11日 下午8:34:00
 */
public class ZipUtil {

    public static void main(String[] args) {
        File file=new File("D:\\sps\\xml2");
        File[] files=file.listFiles();
        File dest=new File(file.getAbsolutePath()+".zip");
        zipFiles(files,dest);
//        File tarDir=new File(file.getAbsolutePath()+"_bak");
//        unZipFile(dest, tarDir);
    }

    /**
     * 压缩文件或者文件夹数组
     * @param srcFiles
     * @param zipFile
     */
    public static void zipFiles(File[] srcFiles, File zipFile) {
    	// 判断压缩后的文件存在不，不存在则创建
    	File parent=zipFile.getParentFile();
    	if(!parent.exists()) {
    		parent.mkdirs();
    	}
    	if(!zipFile.exists()) {
    		try {
				zipFile.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
    	//压缩目录为空 
        if(srcFiles==null||srcFiles.length==0) {
        	return ;
        }
        //创建 ZipOutputStream
        ZipOutputStream zipOutputStream = null;
        try {
            //实例化 FileOutputStream 对象
        	FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
            //实例化 ZipOutputStream 对象
            zipOutputStream = new ZipOutputStream(fileOutputStream);
            //启用压缩
            zipOutputStream.setMethod(ZipOutputStream.DEFLATED);  
            //最大压缩
            zipOutputStream.setLevel(Deflater.BEST_COMPRESSION);
            // 遍历源文件数组
            for (int i = 0; i < srcFiles.length; i++) {
            	writeFile(zipOutputStream,srcFiles[i],"");  
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
        	IOUtils.closeQuietly(zipOutputStream);
        }
    }

    /**
     * zip打包文件夹.退出时自动删除
     * @param file
     * @return
     */
    public static File zipFile(File file) {
    	if(!file.exists()) {
    		return null;
    	}
    	if(!file.isDirectory()) {
    		return null;
    	}
    	File[] files=file.listFiles();
    	if(files.length==0) {
    		return null;
    	}
    	File dest=new File(file.getAbsolutePath()+".zip");
    	zipFiles(files,dest);
    	dest.deleteOnExit();
    	return dest;
    }
    
	/**
	 * 压缩文件或者文件夹数组
	 * @param srcFiles
	 * @param zipFile
	 */
	public static void zipFiles(File[] srcFiles, File zipFile,String charts) {
		// 判断压缩后的文件存在不，不存在则创建
		File parent=zipFile.getParentFile();
		if(!parent.exists()) {
			parent.mkdirs();
		}
		if(!zipFile.exists()) {
			try {
				zipFile.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		//压缩目录为空
		if(srcFiles==null||srcFiles.length==0) {
			return ;
		}
		//创建 ZipOutputStream
		ZipOutputStream zipOutputStream = null;
		try {
			//实例化 FileOutputStream 对象
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			//实例化 ZipOutputStream 对象
			zipOutputStream = new ZipOutputStream(fileOutputStream, Charset.forName(charts));
			//启用压缩
			zipOutputStream.setMethod(ZipOutputStream.DEFLATED);
			//最大压缩
			zipOutputStream.setLevel(Deflater.BEST_COMPRESSION);
			// 遍历源文件数组
			for (int i = 0; i < srcFiles.length; i++) {
				writeFile(zipOutputStream,srcFiles[i],"");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			IOUtils.closeQuietly(zipOutputStream);
		}
	}

	/**
     * 解压文件到指定目录
     * @param zipFile
     * @param targetDir
     */
    public static void unZipFile(File zipFile,File targetDir) {
    	if(!zipFile.exists()) {
    		return ;
    	}
    	if(!targetDir.exists()) {
    		targetDir.mkdirs();
    	}
    	ZipFile zf=null;
		try {
			zf = new ZipFile(zipFile);
			Enumeration<?> e = zf.entries();
	        while (e.hasMoreElements()) {  
	            ZipEntry ze2 = (ZipEntry) e.nextElement();  
	            String entryName = ze2.getName();  
	            File file = new File(targetDir,entryName);  
	            if (ze2.isDirectory()) {  
	                if (!file.exists()) {  
	                	file.mkdirs();  
	                }  
	            } else {  
	            	FileUtils.copyInputStreamToFile(zf.getInputStream(ze2), file);
	            }  
	        }  
		} catch (ZipException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}finally {
			IOUtils.closeQuietly(zf);
		}
    }
    
    /**
     * @param zos
     * @param srcFile
     * @param root 相对路径
     * @throws IOException
     */
    private static void writeFile(ZipOutputStream zos,File srcFile,String root) throws IOException{ 
    	String entryName=srcFile.getName();
    	if(StringUtils.isEmpty(root)) {
    		entryName=srcFile.getName();
    	}else {
    		entryName=root+File.separator+entryName;
    	}
        if (srcFile.isDirectory()) {  
        	ZipEntry zipEntry = new ZipEntry(entryName + "/");  
            zos.putNextEntry(zipEntry);   
            File srcFiles[] = srcFile.listFiles();  
            for (int i = 0; i < srcFiles.length; i++) {  
                writeFile(zos, srcFiles[i],entryName);  
            }  
        } else { 
        	ZipEntry zipEntry = new ZipEntry(entryName);  
            zos.putNextEntry(zipEntry);  
        	FileUtils.copyFile(srcFile, zos);
            //注，在使用缓冲流写压缩文件时，一个条件完后一定要刷新一把，不然可能有的内容就会存入到后面条目中去了  
            zos.flush();  
            zos.closeEntry();
        }  
    } 
}